package com.calvin.study;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.junit.Before;
import org.junit.Test;

import cn.hutool.core.map.MapUtil;
import lombok.Data;

/**
 * https://zhuanlan.zhihu.com/p/422426071
 * java8 使用Optional更优雅的处理非空判断（避免繁琐的使用大量的if/else判断）
 * @author wh
 *
 */
public class OptionalTest01 {

	List<Fruits> fruits = null;

	Map<String, Map<String, Map<String, Object>>> map = new HashMap<>();
	

	@Before
	public void initData() {
		if (null == fruits) {
			fruits = Arrays.asList(new Fruits(1, "红富士苹果", 1, new Double("6.99"), 10),
					new Fruits(2, "阿克苏苹果", 1, new Double("8.99"), 15),
					new Fruits(3, "桑提娜车厘子3J", 2, new Double("29.99"), 350),
					new Fruits(4, "丹东999红颜草莓", 3, new Double("25.99"), 50),
					new Fruits(5, "甘肃花牛苹果", 1, new Double("7.99"), 30));
		}

		Map<String, Map<String, Object>> info = new HashMap();
		
		Map<String, Object> address = new HashMap();
		address.put("address", "武汉市");
		info.put("info", address);

		map.put("user", info);
	}

	@Test
	public void test01() {
		fruits = null;
		// 若fruits对象为空指针，则抛出异常。
		Optional<List<Fruits>> o = Optional.of(fruits);
	}

	@Test
	public void test02() {
		fruits = null;
		// 允许传递null对象，不会抛出异常
		Optional<List<Fruits>> o = Optional.ofNullable(fruits);
		System.out.println(o);
	}

	@Test
	public void test03() throws Exception {
		fruits = null;
		// 返回空的Optional实例
		Optional<List<Fruits>> o = Optional.empty();
		System.out.println(o);
		// 判断Optional实例是否为空
		System.out.println(o.isPresent());
		
		List<Fruits> f1 = o.orElse(new ArrayList());
		System.out.println(f1);

		List<Fruits> f2 = o.orElseGet(ArrayList::new);
		System.out.println(f2);
		//抛出异常
		o.orElseThrow(()->new Exception("这是一个异常"));

	}

	@Test
	public void test04() {
		// 传统方式获取嵌套map中的value，场景：{"user":{"info":{"address":"hz"}}}
		// 需要写多层if语句进行判空
		if (map.get("user") != null) {
			Map<String, Map<String, Object>> user = map.get("user");
			if (MapUtil.isNotEmpty(user.get("info"))) {
				Map<String, Object> info = (Map<String, Object>) user.get("info");
				if (info.get("address") != null) {
					String address = (String) info.get("address");
					System.out.println(address);
				}
			}
		}
		
		//模拟map为空
		map = null;
		String address = (String) Optional.ofNullable(map)
				.map(m -> m.get("user"))
					.map(user -> user.get("info"))
						.map(info -> info.get("address")).orElse(null);
		System.out.println(address);
	}
	
	@Test
	public void test05() {
		User user = new User();
		user.setUserName("王弎拾");
		
		UserInfo userinfo = new UserInfo();
		userinfo.setAddress("武汉");
		user.setUserInfo(userinfo);
		
		String address = Optional.ofNullable(user)
		.map(u->u.getUserInfo())
		.map(info -> info.getAddress()).orElse(null);
		
		System.out.println(address);
		
		
		Optional.ofNullable(user).orElse(new User());
		
		Optional.ofNullable(user).isPresent();
	}
	
	

	@Data
	public class Fruits {
		private Integer id;
		private String name;
		private Integer type;
		private Double money;
		private Integer num;

		public Fruits(Integer id, String name, Integer type, Double money, Integer num) {
			this.id = id;
			this.name = name;
			this.type = type;
			this.money = money;
			this.num = num;
		}
	}
	
	@Data
	public class User{
		private String userName;
		private UserInfo userInfo;
		
	}

	@Data
	public class UserInfo{
		private String address;
	}
}
